Core.Test.registerTest({
	group: "mock",
	name: "The use of stub's __placehold",
	
	_should:
	{
		fail: { "Should fail on disabled stub method call": 1 }
	},
	
	"Should placehold existing method from adaptee": function( )
	{
		function func( ) { return 12; }
		var stub = { fafa: func };
		
		T.Mock.expect( stub, { method: "fafa" } );
		Assert.same( func, stub.__placeholder.fafa );
	},
	
	"Should placehold StubMethod if adaptee's method doesn't exist": function( )
	{
		var stub = { };
		T.Mock.expect( stub, { method: "fafa" } );
		
		Assert.same( T.Mock.StubMethod, stub.__placeholder.fafa );
	},
	
	"Shouldn't placehold method if it's already placeholded (exist)": function( )
	{
		function func( ) { return 12; }
		var stub = { fafa: func };
		
		T.Mock.expect( stub, { method: "fafa" } );
		T.Mock.expect( stub, { method: "fafa" } );
		
		Assert.same( func, stub.__placeholder.fafa );
	},
	
	"Shouldn't placehold method if it's already placeholded (not exist)": function( )
	{
		var stub = { };
		
		T.Mock.expect( stub, { method: "fafa" } );
		T.Mock.expect( stub, { method: "fafa" } );
		
		Assert.same( T.Mock.StubMethod, stub.__placeholder.fafa );
	},
	
	"Should restore mocked methods": function( )
	{
		function func( ) { return 12; }
		var stub = { fafa: func, gaga: func };
		
		T.Mock.expect( stub, { method: "fafa" } );
		T.Mock.expect( stub, { method: "gaga" } );
		
		T.Mock.restore( stub );
		
		Assert.same( func, stub.fafa );
		Assert.same( func, stub.gaga );
		
		Assert.isUndefined( stub.__placeholder );
	},
	
	"Should disable object's methods for mocking": function( )
	{
		function func( ) { return 12; }
		var stub = { fafa: func, gaga: func, value: 12, string: "dada" };
		
		T.Mock.disable( stub );
		
		Assert.isUndefined( stub.value );
		Assert.isUndefined( stub.string );
		
		Assert.areNotEqual( func, stub.fafa );
		Assert.areNotEqual( func, stub.gaga );
	},
	
	"Should fail on disabled stub method call": function( )
	{
		function func( ) { return 12; }
		var stub = { fafa: func, gaga: func, value: 12, string: "dada" };
		
		T.Mock.disable( stub );
		stub.fafa( );
	},
	
	"Should restore disabled stub": function( )
	{
		function func( ) { return 12; }
		var stub = { fafa: func, gaga: func, value: 12, string: "dada" };
		
		T.Mock.disable( stub );
		T.Mock.restore( stub );
		
		Assert.same( 12, stub.value );
		Assert.same( "dada", stub.string );
		
		Assert.same( func, stub.fafa );
		Assert.same( func, stub.gaga );
	}
});

Core.Test.registerTest({
	group: "mock",
	name: "Mocking with direct method invoking order",
	
	_should:
	{
		fail:
		{
			"Should fail if invoked in different order 1": 1,
			"Should fail if invoked in different order 2": 1,
			"Should fail if invoked ignoring methods' callCount": 1,
			"Should fail if there are more invocation than mocked in expectations": 1,
			"Should fail if there are less invocation than mocked in expectations": 1
		}
	},
	
	"Should invoke in given mock order": function( )
	{
		var stub = { };
		
		T.Mock.expect( stub, { method: "fafa" } );
		T.Mock.expect( stub, { method: "gaga" } );
		T.Mock.expect( stub, { method: "dada" } );
		
		stub.fafa( );
		stub.gaga( );
		stub.dada( );
		
		T.Mock.verify( stub );
	},
	
	"Should fail if invoked in different order 1": function( )
	{
		var stub = { };
		
		T.Mock.expect( stub, { method: "fafa" } );
		T.Mock.expect( stub, { method: "gaga" } );
		T.Mock.expect( stub, { method: "dada" } );
		
		stub.gaga( );
		stub.fafa( );
		stub.dada( );
	},
	
	"Should fail if invoked in different order 2": function( )
	{
		var stub = { };
		
		T.Mock.expect( stub, { method: "fafa" } );
		T.Mock.expect( stub, { method: "gaga" } );
		T.Mock.expect( stub, { method: "dada" } );
		
		stub.fafa( );
		stub.dada( );
		stub.gaga( );
	},
	
	"Should invoke in order considering methods' callCount": function( )
	{
		var stub = { };
		
		T.Mock.expect( stub, { method: "fafa", calls: 2 } );
		T.Mock.expect( stub, { method: "gaga" } );
		
		stub.fafa( );
		stub.fafa( );
		stub.gaga( );
		
		T.Mock.verify( stub );
	},
	
	"Should fail if invoked ignoring methods' callCount": function( )
	{
		var stub = { };
		
		T.Mock.expect( stub, { method: "fafa", calls: 2 } );
		T.Mock.expect( stub, { method: "gaga" } );
		
		stub.fafa( );
		stub.gaga( );
	},
	
	"Should fail if there are more invocation than mocked in expectations": function( )
	{
		var stub = { };
		
		T.Mock.expect( stub, { method: "fafa" } );
		T.Mock.expect( stub, { method: "gaga" } );
		
		stub.fafa( );
		stub.gaga( );
		stub.gaga( );
	},
	
	"Should fail if there are less invocation than mocked in expectations": function( )
	{
		var stub = { };
		
		T.Mock.expect( stub, { method: "fafa" } );
		T.Mock.expect( stub, { method: "gaga" } );
		
		stub.fafa( );
		
		T.Mock.verify( stub );
	}
});

Core.Test.registerTest({
	group: "mock",
	name: "Mocking with chainable expectation on the same mocked method",
	
	_should:
	{
		fail:
		{
			"Should fail when invoking with first-method args": 1,
			"Should fail when invoking with second-method args": 1,
			"Should fail when invoking only first expectation": 1,
			"Should fail when invoking chainable out of order": 1,
			"Should fail when invoking chainable in order but with invalid args": 1
		}
	},
	
	"Should invoke same mocked method with different args": function( )
	{
		var argsA = { value: 12 }, argsB = { value: 13 }, stub = { };
		
		T.Mock.expect( stub, { method: "fafa", args: [ argsA ] } );
		T.Mock.expect( stub, { method: "fafa", args: [ argsB ] } );
		
		stub.fafa( argsA );
		stub.fafa( argsB );
		
		T.Mock.verify( stub );
	},
	
	"Should fail when invoking with first-method args": function( )
	{
		var argsA = { value: 12 }, argsB = { value: 13 }, stub = { };
		
		T.Mock.expect( stub, { method: "fafa", args: [ argsA ] } );
		T.Mock.expect( stub, { method: "fafa", args: [ argsB ] } );
		
		stub.fafa( argsA );
		stub.fafa( argsA );
	},
	
	"Should fail when invoking with second-method args": function( )
	{
		var argsA = { value: 12 }, argsB = { value: 13 }, stub = { };
		
		T.Mock.expect( stub, { method: "fafa", args: [ argsA ] } );
		T.Mock.expect( stub, { method: "fafa", args: [ argsB ] } );
		
		stub.fafa( argsB );
		stub.fafa( argsB );
	},
	
	"Should fail when invoking only first expectation": function( )
	{
		var argsA = { value: 12 }, argsB = { value: 13 }, stub = { };
		
		T.Mock.expect( stub, { method: "fafa", args: [ argsA ] } );
		T.Mock.expect( stub, { method: "fafa", args: [ argsB ] } );
		
		stub.fafa( argsA );
		
		T.Mock.verify( stub );
	},
	
	"Should invoke in order & with chainable expectations": function( )
	{
		var argsA = { value: 12 }, argsB = { value: 13 }, stub = { };
		
		T.Mock.expect( stub, { method: "fafa", args: [ argsA ] } );
		T.Mock.expect( stub, { method: "gaga" } );
		T.Mock.expect( stub, { method: "fafa", args: [ argsB ] } );
		
		stub.fafa( argsA );
		stub.gaga( );
		stub.fafa( argsB );
		
		T.Mock.verify( stub );
	},
	
	"Should fail when invoking chainable out of order": function( )
	{
		var argsA = { value: 12 }, argsB = { value: 13 }, stub = { };
		
		T.Mock.expect( stub, { method: "fafa", args: [ argsA ] } );
		T.Mock.expect( stub, { method: "gaga" } );
		T.Mock.expect( stub, { method: "fafa", args: [ argsB ] } );
		
		stub.fafa( argsA );
		stub.fafa( argsB );
		stub.gaga( );
	},
	
	"Should fail when invoking chainable in order but with invalid args": function( )
	{
		var argsA = { value: 12 }, argsB = { value: 13 }, stub = { };
		
		T.Mock.expect( stub, { method: "fafa", args: [ argsA ] } );
		T.Mock.expect( stub, { method: "gaga" } );
		T.Mock.expect( stub, { method: "fafa", args: [ argsB ] } );
		
		stub.fafa( argsA );
		stub.gaga( );
		stub.fafa( argsA );
	}
});

Core.Test.registerTest({
	group: "mock",
	name: "Mocking global packages",
	
	setUp: function( )
	{
		this.func12 = function( ) { return 12; };
		
		window.__tmpGlobal = { fafa: this.func12, gaga: this.func12 };
	},
	
	tearDown: function( )
	{
		delete window.__tmpGlobal;
	},
	
	"Should mock given global package": function( )
	{
		T.Mock.expect( __tmpGlobal, { method: "fafa", returns: 13 } );
		
		Assert.same( 13, __tmpGlobal.fafa( ) );
		Assert.same( 12, __tmpGlobal.gaga( ) );
	},
	
	"Should restore mocked package after success verify": function( )
	{
		T.Mock.expect( __tmpGlobal, { method: "fafa", returns: 13 } );
		T.Mock.restore( __tmpGlobal );
		
		Assert.same( 12, __tmpGlobal.fafa( ) );
		Assert.same( 12, __tmpGlobal.gaga( ) );
	}
});